Análisis complementario para interpretación de resultados
Introducción
Este documento auxiliar permite realizar exploraciones adicionales sobre el dataset gapminder, facilitando la interpretación de resultados y la generación de visualizaciones complementarias.
Carga de librerías y datos
1. Países que cumplen condiciones específicas
Por ejemplo, para la pregunta 1 de la tarea principal:
Filtrar los países asiáticos en 2007 con esperanza de vida mayor a 70 y PBI per cápita mayor a 5000:
# Filtrar países según condiciónpaises_filtrados <- gapminder %>%filter(continent =="Asia", year ==2007, lifeExp >70, gdpPercap >5000)paises_filtrados %>%select(country, lifeExp, gdpPercap)
# A tibble: 14 × 3
country lifeExp gdpPercap
<fct> <dbl> <dbl>
1 Bahrain 75.6 29796.
2 Hong Kong, China 82.2 39725.
3 Iran 71.0 11606.
4 Israel 80.7 25523.
5 Japan 82.6 31656.
6 Korea, Rep. 78.6 23348.
7 Kuwait 77.6 47307.
8 Lebanon 72.0 10461.
9 Malaysia 74.2 12452.
10 Oman 75.6 22316.
11 Saudi Arabia 72.8 21655.
12 Singapore 80.0 47143.
13 Taiwan 78.4 28718.
14 Thailand 70.6 7458.
Visualización: Scatterplot de Esperanza de Vida vs PBI per cápita
# Calcular medianasmediana_lifeExp <-median(paises_filtrados$lifeExp)mediana_gdpPercap <-median(paises_filtrados$gdpPercap)# Scatterplot con leyenda interior de medianas y tendencia LOESSggplot(paises_filtrados, aes(x = gdpPercap, y = lifeExp)) +geom_point(color ='blue', size =5) +geom_text(aes(label = country), nudge_y =1, size =5) +geom_hline(aes(yintercept = mediana_lifeExp, color ="Mediana lifeExp"),linewidth =0.7, alpha =0.5) +geom_vline(aes(xintercept = mediana_gdpPercap, color ="Mediana gdpPercap"),linewidth =0.7, alpha =0.5) +geom_smooth(aes(color ="Tendencia LOESS"), method ="loess", se =TRUE, linewidth =0.7, alpha =0.5) +labs(title ="Países asiáticos en 2007\ncon lifeExp > 70 y gdpPercap > 5000",x ="PBI per cápita",y ="Esperanza de vida",color =NULL) +theme_minimal(base_size =20) +theme(legend.position =c(0.85, 0.05),legend.background =element_rect(fill ="white", color ="black", linewidth =0.5) )
Warning: A numeric `legend.position` argument in `theme()` was deprecated in ggplot2
3.5.0.
ℹ Please use the `legend.position.inside` argument of `theme()` instead.
`geom_smooth()` using formula = 'y ~ x'
Versión interactiva
# Interactive: replica de la gráfica estática con Plotly# Calcular medianasmediana_lifeExp <-median(paises_filtrados$lifeExp)mediana_gdpPercap <-median(paises_filtrados$gdpPercap)p <-ggplot(paises_filtrados, aes(x = gdpPercap, y = lifeExp, text = country)) +geom_point(color ='blue', size =5) +geom_hline(aes(yintercept = mediana_lifeExp, color ="Mediana lifeExp"), linewidth =0.7, alpha =0.5) +geom_vline(aes(xintercept = mediana_gdpPercap, color ="Mediana gdpPercap"), linewidth =0.7, alpha =0.5) +labs(title ="Países asiáticos en 2007\ncon lifeExp > 70 y gdpPercap > 5000",x ="PBI per cápita",y ="Esperanza de vida",color =NULL) +theme_minimal(base_size =12) +theme(legend.position.inside =c(0.95, 0.05),legend.background =element_rect(fill ="white", color ="black", linewidth =0.5) )ggplotly(p, tooltip ="text") %>%layout(legend =list(x =0.95, y =0.05,xanchor ="right", yanchor ="bottom",bgcolor ="white", bordercolor ="black", borderwidth =0.5 ))
Análisis exploratorio de la variable lifeExp
Visualización de la distribución de lifeExp
ggplot(gapminder, aes(x = lifeExp)) +geom_density(fill ='skyblue', color ='darkred', alpha =0.6, linewidth =1) +labs(title ='Densidad de la esperanza de vida (lifeExp)',x ='Esperanza de vida (lifeExp)',y ='Densidad' ) +theme_minimal()
Test de normalidad para lifeExp
# Tamaño de muestra utilizado para los teststamano_muestra <-min(5000, length(gapminder$lifeExp))tamano_muestra
[1] 1704
# Test de Shapiro-Wilk (solo para n <= 5000)shapiro_test <-shapiro.test(sample(gapminder$lifeExp, tamano_muestra))shapiro_test
Shapiro-Wilk normality test
data: sample(gapminder$lifeExp, tamano_muestra)
W = 0.95248, p-value < 2.2e-16
# Test de Kolmogorov-Smirnovks_test <-ks.test(scale(gapminder$lifeExp), "pnorm")
Warning in ks.test.default(scale(gapminder$lifeExp), "pnorm"): ties should not
be present for the one-sample Kolmogorov-Smirnov test
ks_test
Asymptotic one-sample Kolmogorov-Smirnov test
data: scale(gapminder$lifeExp)
D = 0.1049, p-value < 2.2e-16
alternative hypothesis: two-sided
# Test de Anderson-Darlingad_test <-ad.test(gapminder$lifeExp)ad_test
Anderson-Darling normality test
data: gapminder$lifeExp
A = 28.009, p-value < 2.2e-16
Tamaño de muestra utilizado: Para ambos tests se utilizó una muestra de 1704 observaciones de la variable lifeExp.
Interpretación de los resultados: - Shapiro-Wilk normality test: - Estadístico W = 0.95248, p-value < 2.2e-16 - El p-valor extremadamente bajo indica que rechazamos la hipótesis nula de normalidad. Por tanto, la distribución de lifeExp no es normal (al menos para la muestra evaluada). - Kolmogorov-Smirnov test: - Estadístico D = 0.1049, p-value < 2.2e-16 - También rechaza la hipótesis nula de normalidad para la variable estandarizada.
Anderson-Darling normality test:
Estadístico A = 28.009, p-value < 2.2e-16
El resultado refuerza la evidencia contra la normalidad, con un p-valor extremadamente bajo que indica una fuerte discrepancia respecto a la distribución normal, especialmente en las colas.
# Q-Q plotpar(mfrow =c(1, 2))qqnorm(gapminder$lifeExp, main ="QQ-plot de lifeExp")qqline(gapminder$lifeExp, col ="red")qqnorm(scale(gapminder$lifeExp), main ="QQ-plot de lifeExp estandarizada")qqline(scale(gapminder$lifeExp), col ="blue")
par(mfrow =c(1, 1))kurtosis(gapminder$lifeExp)
[1] -1.129098
Análisis visual (Q-Q plots):
En ambos gráficos (para lifeExp y su versión estandarizada) se observa una curvatura en forma de S, lo que indica que los datos se desvían sistemáticamente de la línea teórica que representaría una distribución normal. En particular: - En la cola inferior (cuantiles más bajos), los puntos están por debajo de la línea → hay más valores bajos de lo esperado bajo normalidad. - En la cola superior (cuantiles más altos), los puntos están por encima de la línea → hay más valores altos de lo esperado.
Sin embargo, el exceso de curtosis negativo observado (−1.13) indica que la distribución es platicúrtica, es decir, tiene colas más livianas y una menor concentración alrededor de la media en comparación con una distribución normal. La forma de los Q-Q plots puede entonces explicarse por esta menor curtosis y una posible asimetría leve.
Conclusión: Tanto los tests estadísticos como la evidencia visual aportada por los Q-Q plots indican de forma consistente que la variable lifeExpno sigue una distribución normal. Esto debe tenerse en cuenta al seleccionar métodos estadísticos posteriores, especialmente aquellos que asumen normalidad. Dado el exceso de curtosis negativo y la desviación en los cuantiles extremos, podrían considerarse métodos no paramétricos, transformaciones o enfoques robustos.
# Tamaño de muestra utilizado para los teststamano_muestra <-min(5000, length(aux_gapminder$ingreso_total))tamano_muestra
[1] 1704
# Test de Shapiro-Wilk (solo para n <= 5000)shapiro_test <-shapiro.test(sample(aux_gapminder$ingreso_total, tamano_muestra))shapiro_test
Shapiro-Wilk normality test
data: sample(aux_gapminder$ingreso_total, tamano_muestra)
W = 0.23835, p-value < 2.2e-16
# Test de Kolmogorov-Smirnovks_test <-ks.test(scale(aux_gapminder$ingreso_total), "pnorm")ks_test
Asymptotic one-sample Kolmogorov-Smirnov test
data: scale(aux_gapminder$ingreso_total)
D = 0.39683, p-value < 2.2e-16
alternative hypothesis: two-sided
# Test de Anderson-Darlingad_test <-ad.test(aux_gapminder$ingreso_total)ad_test
Anderson-Darling normality test
data: aux_gapminder$ingreso_total
A = 419.21, p-value < 2.2e-16
# Q-Q plotpar(mfrow =c(1, 2))qqnorm(aux_gapminder$ingreso_total, main ="QQ-plot de ingreso_total")qqline(aux_gapminder$ingreso_total, col ="red")qqnorm(scale(aux_gapminder$ingreso_total), main ="QQ-plot de ingreso_total estandarizada")qqline(scale(aux_gapminder$ingreso_total), col ="blue")
Se evaluó la normalidad de la variable ingreso_total mediante los tests de Shapiro-Wilk, Kolmogorov-Smirnov y Anderson-Darling, utilizando una muestra de 1704 observaciones. En todos los casos, el p-valor fue menor a 2.2e-16, lo que indica una fuerte desviación respecto a la normalidad. El valor extremadamente alto de curtosis (≈ 136) revela una distribución con colas extremadamente pesadas y fuerte asimetría, lo cual también se refleja en los Q-Q plots.
Dado este comportamiento, se aplicó una transformación logarítmica a la variable. Esta transformación reduce la asimetría y la curtosis, acercando la distribución a la normalidad, como se observa en los nuevos Q-Q plots y puede corroborarse mediante nuevos tests de normalidad.
Test de normalidad para log_ingreso_total y log_lifeExp
Tests para log_ingreso_total
# Tamaño de muestra (máximo 5000) según log_ingreso_totaltamano_muestra <-min(5000, nrow(aux_gapminder))tamano_muestra
[1] 1704
# Tests para log_ingreso_total# Shapiro-Wilkshapiro_log_ing <-shapiro.test(sample(aux_gapminder$log_ingreso_total, tamano_muestra))shapiro_log_ing
Shapiro-Wilk normality test
data: sample(aux_gapminder$log_ingreso_total, tamano_muestra)
W = 0.99843, p-value = 0.1131
Asymptotic one-sample Kolmogorov-Smirnov test
data: scale(aux_gapminder$log_ingreso_total)
D = 0.023894, p-value = 0.285
alternative hypothesis: two-sided
# Q-Q plotspar(mfrow =c(1, 2))qqnorm(aux_gapminder$log_ingreso_total, main ="QQ-plot de log_ingreso_total")qqline(aux_gapminder$log_ingreso_total, col ="red")qqnorm(scale(aux_gapminder$log_ingreso_total), main ="QQ-plot de log_ingreso_total (est.)")qqline(scale(aux_gapminder$log_ingreso_total), col ="blue")
# Q-Q plotspar(mfrow =c(1, 2))qqnorm(aux_gapminder$log_lifeExp, main ="QQ-plot de log_lifeExp")qqline(aux_gapminder$log_lifeExp, col ="red")qqnorm(scale(aux_gapminder$log_lifeExp), main ="QQ-plot de log_lifeExp (est.)")qqline(scale(aux_gapminder$log_lifeExp), col ="blue")
par(mfrow =c(1, 1))
📈 Interpretación de las transformaciones de lifeExp e ingreso_total
Transformación de lifeExp:
Aunque se aplicó la transformación logarítmica, los tests de normalidad (Shapiro-Wilk, Kolmogorov-Smirnov y Anderson-Darling) siguen rechazando la hipótesis de normalidad de log_lifeExp con p-valores < 2.2e-16. Además, la curtosis solo pasó de -1.13 a -0.66, indicando una platicurtosis aún moderada. Visualmente, los Q-Q plots muestran que la transformación no alteró sustancialmente la forma o la tendencia de la distribución original. Por tanto, en este caso, la transformación logarítmica no consiguió acercar lifeExp a la normalidad.
Transformación de ingreso_total:
En contraste, ingreso_total presentaba inicialmente una distribución extremadamente sesgada y leptocúrtica (curtosis ≈ 136), lo que fue confirmado por todos los tests de normalidad y los Q-Q plots.
Tras aplicar la transformación logarítmica (log_ingreso_total), se observó una mejora significativa: - El p-valor del test de Shapiro-Wilk aumentó a 0.1131 (no se rechaza normalidad). - El Kolmogorov-Smirnov entregó un p-valor de 0.285 (no rechaza normalidad). - El Anderson-Darling aún rechaza marginalmente (p = 0.01964), pero con un estadístico mucho menor (A ≈ 0.92). - La curtosis (en exceso) bajó a -0.14, acercándose a la de una distribución normal.
Conclusión: Mientras que la transformación logarítmica tuvo poco impacto sobre lifeExp, en ingreso_total logró corregir severas desviaciones, acercando la variable a una distribución normal. Este contraste ilustra la importancia de analizar caso por caso el efecto de las transformaciones.
Ajuste de modelo log-log y análisis de residuos
# Ajustar regresión lineal simplemodelo <-lm(log_lifeExp ~ log_ingreso_total, data = aux_gapminder)# Mostrar resumen del modelosummary(modelo)
Call:
lm(formula = log_lifeExp ~ log_ingreso_total, data = aux_gapminder)
Residuals:
Min 1Q Median 3Q Max
-0.79267 -0.12553 0.02024 0.14398 0.44172
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.392098 0.051407 46.53 <2e-16 ***
log_ingreso_total 0.069707 0.002141 32.56 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.1824 on 1702 degrees of freedom
Multiple R-squared: 0.3838, Adjusted R-squared: 0.3835
F-statistic: 1060 on 1 and 1702 DF, p-value: < 2.2e-16
Modelo ajustado:
Se ajustó un modelo de regresión lineal simple con log_lifeExp como variable dependiente y log_ingreso_total como variable independiente. El modelo resultante fue: \[ \widehat{\log(\text{lifeExp})} = 2.392 + 0.070 \cdot \log(\text{ingreso\_total}) \] donde ambos coeficientes resultaron altamente significativos (p-valor < 2.2e-16).
Interpretación económica:
En este contexto log-log, el coeficiente de log_ingreso_total (≈ 0.07) representa una elasticidad: un aumento del 1% en el ingreso total se asocia, en promedio, con un aumento de aproximadamente 0.07% en la esperanza de vida.
Bondad de ajuste:
El modelo explica cerca del 38% de la variabilidad en log_lifeExp (R² = 0.3838), lo cual es moderado para datos agregados a nivel país-año, donde es esperable una gran heterogeneidad.
# Normalidad de los residuoslillie_test <-lillie.test(residuals(modelo))lillie_test
Lilliefors (Kolmogorov-Smirnov) normality test
data: residuals(modelo)
D = 0.050137, p-value = 9.586e-11
# Homocedasticidad: Test de Breusch-Paganbptest(modelo)
studentized Breusch-Pagan test
data: modelo
BP = 68.254, df = 1, p-value < 2.2e-16
# Visualización de residuospar(mfrow =c(1, 2))plot(modelo$fitted.values, residuals(modelo),main ="Residuos vs Ajustados", xlab ="Valores ajustados", ylab ="Residuos")abline(h =0, lty =2, col ='red')qqnorm(residuals(modelo), main ="QQ-plot de residuos")qqline(residuals(modelo), col ='blue')
par(mfrow =c(1, 1))
Normalidad:
El test de Lilliefors (D = 0.0501, p < 1e-10) rechaza la normalidad de los residuos. Esto indica que, aunque la relación entre las variables es lineal en escala logarítmica, los residuos no son perfectamente normales.
Homocedasticidad:
El test de Breusch-Pagan (BP = 68.25, p < 2.2e-16) también rechaza la hipótesis de homocedasticidad, indicando presencia de heterocedasticidad. Esto se confirma visualmente en el gráfico de “residuos vs ajustados”, donde se aprecia una dispersión creciente.
Visualización:
- El gráfico de residuos vs valores ajustados muestra un patrón de abanico, típico de heterocedasticidad. - El Q-Q plot de los residuos revela desviaciones de la normalidad en las colas, consistentes con los resultados del test de Lilliefors.
Visualización de la relación entre log(ingreso_total) y log(lifeExp)
# Visualizar la relación y la recta de regresiónggplot(aux_gapminder, aes(x = log_ingreso_total, y = log_lifeExp)) +geom_point(alpha =0.3, color ='darkred') +geom_smooth(method ="lm", se =TRUE, color ="blue") +labs(title ="Relación entre log(ingreso_total) y log(lifeExp)",x ="log(ingreso_total)",y ="log(lifeExp)" ) +theme_minimal()
`geom_smooth()` using formula = 'y ~ x'
El gráfico de dispersión entre log_ingreso_total y log_lifeExp, junto con la recta de regresión, confirma una relación positiva y aproximadamente lineal en la escala logarítmica. El uso del logaritmo mejora claramente la linealidad y permite interpretar la pendiente en términos de elasticidad.
Conclusión general de las transformaciones y el ajuste log-log
Existe una relación positiva y estadísticamente significativa entre el ingreso total y la esperanza de vida cuando ambas variables son logarítmicas.
El modelo capta una proporción moderada de la variabilidad, pero sus residuos presentan problemas de normalidad y homocedasticidad.
A pesar de estos problemas, el ajuste log-log es conceptualmente apropiado para capturar la relación económica subyacente. Para una modelización más rigurosa, se podría considerar:
Uso de errores robustos (HC standard errors),
Modelos de regresión robusta,
O transformaciones adicionales para corregir la heterocedasticidad.
Visualizaciones sobre la categorización de esperanza de vida (Ejercicio 1.3)
1. Línea apilada: proporción de categorías a lo largo del tiempo
# Data frame con categoríaexp_cat_df <- gapminder %>%mutate(exp_cat =case_when( lifeExp <50~"baja", lifeExp >=50& lifeExp <70~"media", lifeExp >=70~"alta" ) )# Proporción por año y categoríaprop_exp_time <- exp_cat_df %>%group_by(year, exp_cat) %>%summarise(n =n(), .groups ="drop") %>%group_by(year) %>%mutate(prop = n /sum(n))# Definir paleta consistentecolores_exp_cat <-c("baja"="#e74c3c", "media"="#f1c40f", "alta"="#27ae60")# Línea apilada con colores fijosggplot(prop_exp_time, aes(x = year, y = prop, fill = exp_cat)) +geom_area(alpha =0.7, color ="grey40") +labs(title ="Proporción de categorías de esperanza de vida a lo largo del tiempo",x ="Año",y ="Proporción",fill ="Categoría" ) +scale_y_continuous(labels = scales::percent_format()) +scale_fill_manual(values = colores_exp_cat) +theme_minimal(base_size =14)
Este gráfico permite visualizar cómo la distribución de las categorías de esperanza de vida (baja, media, alta) evoluciona a lo largo del tiempo, facilitando la identificación de tendencias globales y transiciones demográficas en el conjunto de países analizados.
Análisis de tendencias temporales por continente
Evolución de la esperanza de vida por continente
# Gráfico de esperanza de vida vs tiempo por continenteggplot(gapminder, aes(x = year, y = lifeExp, color = continent)) +geom_point(alpha =0.3) +geom_smooth(method ="loess", se =TRUE) +labs(title ="Evolución de la esperanza de vida por continente",x ="Año",y ="Esperanza de vida",color ="Continente" ) +theme_minimal(base_size =12) +scale_color_brewer(palette ="Set2")
`geom_smooth()` using formula = 'y ~ x'
Este gráfico muestra cómo la esperanza de vida ha evolucionado de manera diferente en cada continente. Las bandas sombreadas representan el intervalo de confianza de la tendencia LOESS, revelando tanto la tendencia central como la variabilidad en cada región.
Evolución del PBI per cápita por continente
# Gráfico de PBI per cápita vs tiempo por continenteggplot(gapminder, aes(x = year, y = gdpPercap, color = continent)) +geom_point(alpha =0.3) +geom_smooth(method ="loess", se =TRUE) +labs(title ="Evolución del PBI per cápita por continente",x ="Año",y ="PBI per cápita",color ="Continente" ) +theme_minimal(base_size =12) +scale_color_brewer(palette ="Set2") +scale_y_continuous(labels = scales::dollar_format())
`geom_smooth()` using formula = 'y ~ x'
La visualización del PBI per cápita revela patrones distintos de crecimiento económico entre continentes. Las tendencias suavizadas LOESS y sus intervalos de confianza permiten apreciar tanto la magnitud como la variabilidad del desarrollo económico en cada región.
Relación entre esperanza de vida y PIB per cápita (2007)
# Identificar top 10 países por esperanza de vida en 2007top10_2007 <- gapminder %>%filter(year ==2007) %>%arrange(desc(lifeExp)) %>%slice_head(n =10) %>%mutate(is_top10 =TRUE)# Preparar datos para visualizacióndata_2007 <- gapminder %>%filter(year ==2007) %>%left_join(select(top10_2007, country, is_top10), by ="country") %>%mutate(is_top10 =replace_na(is_top10, FALSE),label =if_else(is_top10, country, NA_character_) )# Crear gráficoggplot(data_2007, aes(x = gdpPercap, y = lifeExp)) +# Puntos basegeom_point(aes(color = is_top10, size = is_top10, alpha = is_top10)) +# Etiquetas para top 10geom_text_repel(aes(label = label),nudge_x =0.05,size =3,segment.color ="grey50" ) +# Línea de tendenciageom_smooth(method ="lm", color ="grey30", se =FALSE) +# Configuración estéticascale_color_manual(values =c("FALSE"="grey70", "TRUE"="#e41a1c") ) +scale_size_manual(values =c("FALSE"=2, "TRUE"=3) ) +scale_alpha_manual(values =c("FALSE"=0.5, "TRUE"=1) ) +scale_x_log10(labels = scales::dollar_format()) +labs(title ="Relación entre PIB per cápita y esperanza de vida (2007)",subtitle ="Destacando los 10 países con mayor esperanza de vida",x ="PIB per cápita (escala logarítmica)",y ="Esperanza de vida" ) +theme_minimal(base_size =12) +theme(legend.position ="none",plot.subtitle =element_text(color ="grey40") )
`geom_smooth()` using formula = 'y ~ x'
Warning: Removed 132 rows containing missing values or values outside the scale range
(`geom_text_repel()`).
Warning: ggrepel: 10 unlabeled data points (too many overlaps). Consider
increasing max.overlaps
Esta visualización muestra la relación entre PIB per cápita y esperanza de vida en 2007, destacando en rojo los 10 países con mayor esperanza de vida. Los países del top 10 tienden a concentrarse en la parte superior derecha del gráfico, confirmando la asociación entre alto desarrollo económico y mayor longevidad.
Visualizaciones de distribuciones antes y después de estandarizar variables
Confirmar media y desviación de variables estandarizadas
# Calcular media y sd usando el objeto tmp_scaled generado anteriormentesummary_estandarizado_aux <- tmp_scaled %>%group_by(variable) %>%summarise(media =mean(valor, na.rm =TRUE),desvio =sd(valor, na.rm =TRUE),.groups ="drop" )# Mostrar resultadossummary_estandarizado_aux %>% knitr::kable(caption ="Media y desviación estándar de variables estandarizadas" )
Media y desviación estándar de variables estandarizadas
variable
media
desvio
gdpPercap
0
1
lifeExp
0
1
pop
0
1
Visualizaciones para ejercicio 1.14
data_change <- gapminder %>%group_by(country) %>%arrange(year) %>%mutate(lifeExp_diff = lifeExp -lag(lifeExp)) %>%filter(year ==2007) %>%mutate(change =if_else(lifeExp_diff >0, "Aumentó", "No aumentó"))data_change %>%ggplot(aes(x = change, y = gdpPercap, color = change)) +geom_jitter(width =0.2, alpha =0.6, size =2) +stat_summary(fun = mean, geom ="point", shape =18, size =4, color ="black") +labs(title ="GDP per cápita en 2007 según cambio en esperanza de vida",x ="Cambio en lifeExp",y ="GDP per cápita (USD)" ) +theme_minimal()
Se observa que la mayoría de los países experimentaron un aumento en la esperanza de vida entre 2002 y 2007. Dentro de ese grupo, hay una gran dispersión en el ingreso per cápita, incluyendo tanto países de ingresos bajos como muy altos. En contraste, los pocos países donde no aumentó la esperanza de vida presentan niveles consistentemente bajos de ingreso. Esto refuerza la asociación entre desarrollo económico y mejora en indicadores de salud.
data_change %>%ggplot(aes(x = gdpPercap, y = change, fill = change)) +geom_density_ridges(scale =1.5, alpha =0.6, show.legend =FALSE) +labs(title ="Distribución de GDP per cápita según cambio en esperanza de vida (2007)",x ="GDP per cápita",y ="" ) +theme_minimal()
Picking joint bandwidth of 3850
Aunque el gráfico es estéticamente atractivo, puede ser engañoso, especialmente en el grupo “No aumentó”, que contiene muy pocos países. La suavización genera una ilusión de densidad o volumen que en realidad no representa la escasez de datos. Por eso, es clave aclarar que las curvas no reflejan tamaños muestrales proporcionales y que deben interpretarse con precaución.
# Facet wrap de `gdpPercap` según año — escala logarítmicag2 <-ggplot(gapminder, aes(x = gdpPercap, fill = continent)) +geom_density(alpha =0.5) +scale_x_log10(labels = scales::label_log()) +facet_wrap(~year, nrow =3, ncol =4) +labs(title ="Facet wrap de PIB per cápita según año",subtitle ="Versión preliminar con escala logarítmica — distribución aún no optimizada",x ="PIB per cápita (USD, escala log)",y ="Densidad",fill ="Continente" ) +theme_minimal() + paleta_fill_continentesg2
✅ Alternativa 1: Gráfico de línea apilada (área) de proporciones de gdpPercap × pop por continente
Qué muestra:
Proporción del ingreso total mundial aportado por cada continente en cada año (ingreso total = gdpPercap * pop).
Facetear por año no tiene sentido acá, así que esta opción es complementaria, no sustituta de 2.3.
gapminder %>%mutate(ingreso_total = gdpPercap * pop) %>%group_by(year, continent) %>%summarise(ingreso =sum(ingreso_total), .groups ="drop") %>%group_by(year) %>%mutate(prop = ingreso /sum(ingreso)) %>%ggplot(aes(x = year, y = prop, fill = continent)) +geom_area(alpha =0.8) +scale_y_continuous(labels = scales::percent_format()) +scale_fill_brewer(palette ="Set1") +labs(title ="Proporción del PIB mundial aportado por continente",x ="Año",y ="Proporción del ingreso total",fill ="Continente" ) +theme_minimal()
✅ Alternativa 2: Histograma facetado (gdpPercap con continentes)
Qué muestra:
Distribución de países según su PIB per cápita.
Escala logarítmica para evitar la distorsión por outliers.
Cada panel representa un año → respeta literalmente la consigna.
g1 <- gapminder %>%ggplot(aes(x = gdpPercap, fill = continent)) +geom_histogram(bins =25, alpha =0.5, position ="identity") +scale_x_continuous(labels = scales::label_number(scale_cut = scales::cut_short_scale())) +facet_wrap(~ year, ncol =4) +labs(title ="Distribución del PIB per cápita por año",subtitle ="Escala original",x ="PIB per cápita (USD)",y ="Frecuencia",fill ="Continente" ) +theme_minimal() + paleta_fill_continentesg1
g2 <- gapminder %>%ggplot(aes(x =log10(gdpPercap), fill = continent)) +geom_histogram(bins =25, alpha =0.5, position ="identity") +scale_x_log10(labels = scales::label_log()) +facet_wrap(~ year, ncol =4) +labs(title ="Distribución logarítmica del PIB per cápita por año",subtitle ="Facetas por año, escala log10",x ="PIB per cápita (escala log)",y ="Frecuencia",fill ="Continente" ) +theme_minimal() + paleta_fill_continentesg2
✅ Alternativa 3: Evolución de la mediana de gdpPercap por continente (línea temporal)
Este gráfico muestra cómo evoluciona el nivel típico (mediana) del PIB per cápita en cada continente. Es ideal para mostrar tendencias macroeconómicas.
g1 <- gapminder %>%group_by(year, continent) %>%summarise(median_gdp =median(gdpPercap), .groups ="drop") %>%ggplot(aes(x = year, y = median_gdp, color = continent)) +geom_line(size =1) +geom_point(size =1.5) +scale_y_continuous(labels = scales::label_number(scale_cut = scales::cut_short_scale())) +labs(title ="Evolución de la mediana del PIB per cápita por continente",subtitle ="Escala original",x ="Año",y ="Mediana del PIB per cápita (USD)",color ="Continente" ) +theme_minimal() + paleta_continentes
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
g1
g2 <- gapminder %>%group_by(year, continent) %>%summarise(median_gdp =median(gdpPercap), .groups ="drop") %>%ggplot(aes(x = year, y = median_gdp, color = continent)) +geom_line(size =1) +geom_point(size =1.5) +scale_y_log10(labels = scales::label_log()) +labs(title ="Evolución de la mediana del PIB per cápita por continente",x ="Año",y ="Mediana del PIB per cápita (USD, log)",color ="Continente" ) +theme_minimal() + paleta_continentesg2
✅ Alternativa 4: Evolución de toda la distribución — faceteado por año + violines
Esto sí cumple estrictamente con la consigna “Facet wrap según año”, pero en lugar de usar geom_density(), usamos violin plots para mostrar la dispersión y forma en cada panel:
g1 <- gapminder %>%ggplot(aes(x = continent, y = gdpPercap, fill = continent)) +geom_violin(scale ="width", draw_quantiles =c(0.25, 0.5, 0.75)) +scale_y_continuous(labels = scales::label_number(scale_cut = scales::cut_short_scale())) +facet_wrap(~ year, ncol =4) +labs(title ="Distribución del PIB per cápita por continente en cada año",subtitle ="Escala original",x ="Continente",y ="PIB per cápita (USD)",fill ="Continente" ) +theme_minimal() + paleta_fill_continentes +theme(axis.text.x =element_text(angle =30, hjust =1))g1
g2 <- gapminder %>%ggplot(aes(x = continent, y = gdpPercap, fill = continent)) +geom_violin(scale ="width", draw_quantiles =c(0.25, 0.5, 0.75)) +scale_y_log10(labels = scales::label_log()) +facet_wrap(~year, ncol =4) +labs(title ="Distribución del PIB per cápita por continente en cada año",subtitle ="Escala logarítmica para evitar distorsión por outliers",x ="Continente",y ="PIB per cápita (USD, log escala)",fill ="Continente" ) +theme_minimal() + paleta_fill_continentes +theme(axis.text.x =element_text(angle =30, hjust =1))g2
✅ Alternativa 5: Histograma facetado de log(gdpPercap) por año (sin continentes)
g1 <- gapminder %>%ggplot(aes(x = gdpPercap)) +geom_histogram(bins =25, fill ="steelblue", color ="white", alpha =0.8) +scale_x_continuous(labels = scales::label_number(scale_cut = scales::cut_short_scale())) +facet_wrap(~ year, ncol =4) +labs(title ="Distribución del PIB per cápita por año",subtitle ="Sin separar por continente — escala original",x ="PIB per cápita (USD)",y ="Frecuencia" ) +theme_minimal()g1
g2 <- gapminder %>%ggplot(aes(x =log10(gdpPercap))) +geom_histogram(bins =25, fill ="steelblue", color ="white", alpha =0.8) +scale_x_log10(labels = scales::label_log()) +facet_wrap(~ year, ncol =4) +labs(title ="Distribución del PIB per cápita (escala log) por año",subtitle ="Se muestra la distribución de países sin separar por continente",x ="PIB per cápita (escala log)",y ="Frecuencia" ) +theme_minimal()g2
✅ Alternativa 6: Diagrama de violín facetado por año (sin continentes)
# Escala originalg1 <- gapminder %>%ggplot(aes(x =factor(year), y = gdpPercap)) +geom_violin(fill ="darkorange", alpha =0.7,draw_quantiles =c(0.25, 0.5, 0.75)) +scale_y_continuous(labels = scales::label_number(scale_cut = scales::cut_short_scale())) +labs(title ="Distribución del PIB per cápita por año",subtitle ="Violines verticales — escala original",x ="Año",y ="PIB per cápita (USD)" ) +theme_minimal()# Escala logarítmicag2 <- gapminder %>%ggplot(aes(x =factor(year), y = gdpPercap)) +geom_violin(fill ="darkorange", alpha =0.7,draw_quantiles =c(0.25, 0.5, 0.75)) +scale_y_log10(labels = scales::label_log()) +labs(title ="Distribución del PIB per cápita por año (escala log)",subtitle ="Violines verticales — escala logarítmica",x ="Año",y ="PIB per cápita (USD, log escala)" ) +theme_minimal()# Visualizacióng1
g2
✅ **Alternativa 7: Split‐violin de gdpPercap vs lag(gdpPercap) por continente
# Preparo datos con lag de 1 año por paísdf_halves <- gapminder %>%group_by(country) %>%arrange(year) %>%mutate(lag_gdp =lag(gdpPercap)) %>%ungroup() %>%filter(!is.na(lag_gdp))# Split‐violin en log‐escala, faceteado por añoggplot(df_halves, aes(x = continent, fill = continent)) +geom_half_violin(aes(y = lag_gdp),side ="l",alpha =0.6,scale ="width",trim =FALSE ) +geom_half_violin(aes(y = gdpPercap),side ="r",alpha =0.6,scale ="width",trim =FALSE ) +scale_y_log10(labels =label_log()) +facet_wrap(~year, ncol =4) +labs(title ="PIB per cápita: lag vs actual cada año",subtitle ="Violin por continente (escala log)",y ="PIB per cápita (USD, log escala)",fill ="Continente" ) +theme_minimal() + paleta_fill_continentes +theme(axis.text.x =element_text(angle =30, hjust =1),legend.position =c(0.9, 0.025) )
✅ Diagrama de mosaico de continent contra una categoría derivada de lifeExp
library(ggalluvial)data_mosaic <- gapminder %>%mutate(lifeExp_cat =case_when( lifeExp <50~"baja", lifeExp <70~"media",TRUE~"alta" ) )data_mosaic %>%count(continent, lifeExp_cat) %>%ggplot(aes(axis1 = continent, axis2 = lifeExp_cat, y = n)) +geom_alluvium(aes(fill = lifeExp_cat), width =1/12, alpha =0.8) +geom_stratum(width =1/12, fill ="grey90") +geom_label(stat ="stratum", aes(label =after_stat(stratum))) +scale_x_discrete(limits =c("continent", "lifeExp_cat"),expand =c(.1, .1) ) +labs(title ="Alluvial: flujo de países por categoría de esperanza",x ="",y ="Cantidad de países",fill ="LifeExp" ) +theme_minimal(base_size =12)
Propuesta de visualización animada al estilo Hans Rosling
Concepto
Bubble chart:
x = gdpPercap (escala log),
y = lifeExp,
size = pop,
color = continent,
frame = year.
Esto replica el clásico Gapminder interactivo. Se puede exportar como GIF (gganimate) o mantenerlo interactivo (plotly).
library(plotly)plot_ly( gapminder,x =~gdpPercap, y =~lifeExp,size =~pop, color =~continent,frame =~year, text =~country,type ='scatter', mode ='markers',sizes =c(10, 100),marker =list(line =list(width =0))) %>%layout(title ='Gapminder dinámico',xaxis =list(type ='log', title ='PIB per cápita (USD, log)'),yaxis =list(title ='Esperanza de vida (años)') ) %>%animation_opts(frame =1000, easing ="linear", redraw =FALSE )
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.
Warning: `line.width` does not currently support multiple values.